/*
 * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
 * Description: host uvc mode interface
 * Author: HiMobileCam Reference Develop Team
 * Create: 2019-09-30
 */

#include "hi_math.h"
#include "mpi_sys.h"
#include "mpi_vb.h"
#include "mpi_vgs.h"
#include "mpi_venc.h"
#include "mpi_vo.h"
#include "hi_product_statemng.h"
#include "hi_product_statemng_inner.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#ifdef CONFIG_USB_HOST_UVC_SUPPORT

typedef struct {
    HI_U32 width;
    HI_U32 height;
    PIXEL_FORMAT_E pixfmt;
} PDT_STATEMNG_HostUvcPixfmtAttr;

static VB_POOL PDT_STATEMNG_GetVBPool(HI_U32 blkSize)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    HI_PDT_MEDIA_CFG_S stMediaCfg;
    HI_S32 ret = HI_PDT_PARAM_GetMediaCfg(stateMngCtx->enCurrentWorkMode, stateMngCtx->astCamCtx, &stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, ret, "get media config");

    for (HI_S32 i = MIN(stMediaCfg.stVBCfg.u32MaxPoolCnt, HI_PDT_MEDIA_VB_MAX_POOLS) - 1; i >= 0; i--) {
        if (stMediaCfg.stVBCfg.astCommPool[i].u32BlkCnt >= 1 &&
            stMediaCfg.stVBCfg.astCommPool[i].u32BlkSize >= blkSize) {
            return (VB_POOL)i;
        }
    }
    MLOGE("blkSize:%d is not found.\n", blkSize);
    return VB_INVALID_POOLID;
}

static HI_S32 PDT_STATEMNG_CreateDstFrameInfo(const VIDEO_FRAME_INFO_S *srcFrmInfo,
                                              const PDT_STATEMNG_HostUvcPixfmtAttr *attr,
                                              VIDEO_FRAME_INFO_S *dsrFrmInfo)
{
    memcpy(dsrFrmInfo, srcFrmInfo, sizeof(VIDEO_FRAME_INFO_S));
    dsrFrmInfo->stVFrame.u32Width = attr->width;
    dsrFrmInfo->stVFrame.u32Height = attr->height;
    dsrFrmInfo->stVFrame.u32Stride[0] = ALIGN_DOWN(attr->width, 16U);
    dsrFrmInfo->stVFrame.u32Stride[1] = dsrFrmInfo->stVFrame.u32Stride[0];
    dsrFrmInfo->stVFrame.u32Stride[2] = dsrFrmInfo->stVFrame.u32Stride[0];
    HI_U32 size = dsrFrmInfo->stVFrame.u32Stride[0] * dsrFrmInfo->stVFrame.u32Height * 2U;
    VB_BLK vbBlkHdl = HI_MPI_VB_GetBlock(PDT_STATEMNG_GetVBPool(size), size, NULL);
    if (vbBlkHdl == VB_INVALID_HANDLE) {
        MLOGE("HI_MPI_VB_GetBlock failed! size=%d\n", size);
        return HI_FAILURE;
    }
    dsrFrmInfo->stVFrame.u64PhyAddr[0] = HI_MPI_VB_Handle2PhysAddr(vbBlkHdl);
    dsrFrmInfo->stVFrame.u64PhyAddr[1] =
        dsrFrmInfo->stVFrame.u64PhyAddr[0] + dsrFrmInfo->stVFrame.u32Stride[0] * dsrFrmInfo->stVFrame.u32Height;
    dsrFrmInfo->stVFrame.u64PhyAddr[2] =
        dsrFrmInfo->stVFrame.u64PhyAddr[1] + dsrFrmInfo->stVFrame.u32Stride[0] * dsrFrmInfo->stVFrame.u32Height / 2U;
    dsrFrmInfo->stVFrame.u64VirAddr[0] = (HI_U64)(HI_UL)HI_MPI_SYS_Mmap(dsrFrmInfo->stVFrame.u64PhyAddr[0], size);
    dsrFrmInfo->stVFrame.u64VirAddr[1] =
        dsrFrmInfo->stVFrame.u64VirAddr[0] + dsrFrmInfo->stVFrame.u32Stride[0] * dsrFrmInfo->stVFrame.u32Height;
    dsrFrmInfo->stVFrame.u64VirAddr[2] =
        dsrFrmInfo->stVFrame.u64VirAddr[1] + dsrFrmInfo->stVFrame.u32Stride[0] * dsrFrmInfo->stVFrame.u32Height / 2U;
    dsrFrmInfo->stVFrame.enPixelFormat = attr->pixfmt;
    dsrFrmInfo->u32PoolId = HI_MPI_VB_Handle2PoolId(vbBlkHdl);
    dsrFrmInfo->enModId = HI_ID_VGS;
    return HI_SUCCESS;
}

static HI_S32 PDT_STATEMNG_ConvertPixfmt(const VIDEO_FRAME_INFO_S *srcFrmInfo,
                                         const PDT_STATEMNG_HostUvcPixfmtAttr *attr, VIDEO_FRAME_INFO_S *dsrFrmInfo)
{
    HI_S32 ret = PDT_STATEMNG_CreateDstFrameInfo(srcFrmInfo, attr, dsrFrmInfo);
    if (ret != HI_SUCCESS) {
        return HI_FAILURE;
    }

    VGS_HANDLE vgsHdl;
    ret = HI_MPI_VGS_BeginJob(&vgsHdl);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MPI_VGS_BeginJob failed\n");
        goto end;
    }

    VGS_TASK_ATTR_S stTask;
    memcpy(&stTask.stImgIn, srcFrmInfo, sizeof(VIDEO_FRAME_INFO_S));
    memcpy(&stTask.stImgOut, dsrFrmInfo, sizeof(VIDEO_FRAME_INFO_S));
    ret = HI_MPI_VGS_AddScaleTask(vgsHdl, &stTask, VGS_SCLCOEF_NORMAL);
    if (ret != HI_SUCCESS) {
        HI_MPI_VGS_CancelJob(vgsHdl);
        MLOGE("HI_MPI_VGS_AddScaleTask failed\n");
        goto end;
    }

    ret = HI_MPI_VGS_EndJob(vgsHdl);
    if (ret != HI_SUCCESS) {
        HI_MPI_VGS_CancelJob(vgsHdl);
        MLOGE("HI_MPI_VGS_EndJob failed\n");
        goto end;
    }
    dsrFrmInfo->enModId = HI_ID_USER;
    return HI_SUCCESS;
end:
    HI_MPI_VB_ReleaseBlock(HI_MPI_VB_PhysAddr2Handle(dsrFrmInfo->stVFrame.u64PhyAddr[0]));
    return ret;
}

static HI_VOID PDT_STATEMNG_SendHostUvcFrameToThmVenc(const VIDEO_FRAME_INFO_S *srcFrmInfo)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    VENC_CHN thmHdl =
        stateMngCtx->stRecCtx.astRecTaskCtx[PDT_STATEMNG_BACK_CAMID].stRecMngAttr.astFileAttr[0].stDataSource.ThmHdl;
    VENC_CHN_STATUS_S status;
    HI_S32 ret = HI_MPI_VENC_QueryStatus(thmHdl, &status);
    if (ret != HI_SUCCESS || status.u32LeftRecvPics == 0) {
        return;
    }
    HI_MEDIA_VIDEOINFO_S videoInfo;
    ret = HI_PDT_MEDIA_GetVideoInfo(thmHdl, &videoInfo);
    if (ret != HI_SUCCESS) {
        return;
    }
    VIDEO_FRAME_INFO_S subFrmInfo;
    PDT_STATEMNG_HostUvcPixfmtAttr thmAttr = {
        videoInfo.stVencAttr.stTypeAttr.u32Width,
        videoInfo.stVencAttr.stTypeAttr.u32Height,
        PIXEL_FORMAT_YVU_SEMIPLANAR_420
    };
    ret = PDT_STATEMNG_ConvertPixfmt(srcFrmInfo, &thmAttr, &subFrmInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("PDT_STATEMNG_ConvertPixfmt error ret:0x%x\n", ret);
    } else {
        ret = HI_MPI_VENC_SendFrame(thmHdl, &subFrmInfo, 0);
        HI_MPI_VB_ReleaseBlock(HI_MPI_VB_PhysAddr2Handle(subFrmInfo.stVFrame.u64PhyAddr[0]));
        if (ret != HI_SUCCESS) {
            MLOGE("HI_MPI_VENC_SendFrame error ret:0x%x\n", ret);
        }
    }
}

static HI_VOID PDT_STATEMNG_SendHostUvcFrameToRecVenc(const VIDEO_FRAME_INFO_S *srcFrmInfo,
                                                      VIDEO_FRAME_INFO_S *mainFrmInfo)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    if ((stateMngCtx->stRecCtx.bRecStarted != HI_TRUE) ||
        (stateMngCtx->astCamCtx[PDT_STATEMNG_BACK_CAMID].bEnable != HI_TRUE) ||
        (stateMngCtx->stRecCtx.astRecTaskCtx[PDT_STATEMNG_BACK_CAMID].bEnable != HI_TRUE)) {
        return;
    }

    PDT_STATEMNG_HostUvcPixfmtAttr mainAttr = {
        stateMngCtx->hostUvc.width,
        stateMngCtx->hostUvc.height,
        PIXEL_FORMAT_YVU_SEMIPLANAR_420
    };
    HI_S32 ret = PDT_STATEMNG_ConvertPixfmt(srcFrmInfo, &mainAttr, mainFrmInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("PDT_STATEMNG_ConvertPixfmt error ret:0x%x\n", ret);
    } else {
        HI_RECMNG_ATTR_S *recmngAttr = &stateMngCtx->stRecCtx.astRecTaskCtx[PDT_STATEMNG_BACK_CAMID].stRecMngAttr;
        VENC_CHN vencHdl = recmngAttr->astFileAttr[0].stDataSource.aVencHdl[0];
        ret = HI_MPI_VENC_SendFrame(vencHdl, mainFrmInfo, 0);
        if (ret != HI_SUCCESS) {
            MLOGE("HI_MPI_VENC_SendFrame error ret:0x%x\n", ret);
        }
    }

    PDT_STATEMNG_SendHostUvcFrameToThmVenc(srcFrmInfo);
}

static HI_VOID PDT_STATEMNG_SendHostUvcFrameToSanpVenc(const VIDEO_FRAME_INFO_S *srcFrmInfo,
                                                       VIDEO_FRAME_INFO_S *mainFrmInfo)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    if (stateMngCtx->stPhotoCtx.stPhotoTaskCtx[PDT_STATEMNG_BACK_CAMID].bEnable != HI_TRUE) {
        return;
    }
    VENC_CHN vencHdl = stateMngCtx->stPhotoCtx.stPhotoTaskCtx[PDT_STATEMNG_BACK_CAMID].stPhotoAttr.stPhotoSRC.VencHdl;
    VENC_CHN_STATUS_S status;
    HI_S32 ret = HI_MPI_VENC_QueryStatus(vencHdl, &status);
    if (ret != HI_SUCCESS || status.u32LeftRecvPics == 0) {
        return;
    }
    if (mainFrmInfo->u32PoolId == VB_INVALID_POOLID) {
        PDT_STATEMNG_HostUvcPixfmtAttr mainAttr = {
            stateMngCtx->hostUvc.width,
            stateMngCtx->hostUvc.height,
            PIXEL_FORMAT_YVU_SEMIPLANAR_420
        };
        ret = PDT_STATEMNG_ConvertPixfmt(srcFrmInfo, &mainAttr, mainFrmInfo);
        if (ret != HI_SUCCESS) {
            MLOGE("PDT_STATEMNG_ConvertPixfmt error ret:0x%x\n", ret);
            return;
        }
    }

    ret = HI_MPI_VENC_SendFrame(vencHdl, mainFrmInfo, 0);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MPI_VENC_SendFrame error ret:0x%x\n", ret);
    }
}

static HI_VOID PDT_STATEMNG_SendHostUvcFrameToVenc(const VIDEO_FRAME_INFO_S *srcFrmInfo)
{
    VIDEO_FRAME_INFO_S mainFrmInfo;
    mainFrmInfo.u32PoolId = VB_INVALID_POOLID;
    PDT_STATEMNG_SendHostUvcFrameToRecVenc(srcFrmInfo, &mainFrmInfo);
    PDT_STATEMNG_SendHostUvcFrameToSanpVenc(srcFrmInfo, &mainFrmInfo);
    if (mainFrmInfo.u32PoolId != VB_INVALID_POOLID) {
        HI_MPI_VB_ReleaseBlock(HI_MPI_VB_PhysAddr2Handle(mainFrmInfo.stVFrame.u64PhyAddr[0]));
    }
}

static HI_VOID PDT_STATEMNG_SendHostUvcFrameToVo(const VIDEO_FRAME_INFO_S *srcFrmInfo)
{
    HI_S32 ret;
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    if (stateMngCtx->s32PreviewCamID != PDT_STATEMNG_BACK_CAMID || stateMngCtx->bScreenDormantStatus == HI_TRUE) {
        return;
    }
    VO_CHN_ATTR_S voChnAttr;
    ret = HI_MPI_VO_GetChnAttr(0, 0, &voChnAttr);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MPI_VO_GetChnAttr error ret:0x%x\n", ret);
        return;
    }
    PDT_STATEMNG_HostUvcPixfmtAttr voAttr = {
        voChnAttr.stRect.u32Width,
        voChnAttr.stRect.u32Height,
        PIXEL_FORMAT_YVU_SEMIPLANAR_420
    };
    VIDEO_FRAME_INFO_S voFrmInfo;
    ret = PDT_STATEMNG_ConvertPixfmt(srcFrmInfo, &voAttr, &voFrmInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("STATEMNG_HostUvcPixfmtConversion error ret:0x%x\n", ret);
    } else {
        ret = HI_MPI_VO_SendFrame(0, 0, &voFrmInfo, 0);
        HI_MPI_VB_ReleaseBlock(HI_MPI_VB_PhysAddr2Handle(voFrmInfo.stVFrame.u64PhyAddr[0]));
        if (ret != HI_SUCCESS) {
            MLOGE("HI_MPI_VO_SendFrame error ret:0x%x\n", ret);
        }
    }
}

HI_VOID PDT_STATEMNG_ProcHostUvcFrame(const HI_USB_HostUvcFrameInfo *frame)
{
    VB_BLK vbBlk = HI_MPI_VB_PhysAddr2Handle(frame->yuv.phyAddr[0]);
    VIDEO_FRAME_INFO_S stVideoFrame;
    memset(&stVideoFrame, 0, sizeof(VIDEO_FRAME_INFO_S));
    stVideoFrame.u32PoolId = HI_MPI_VB_Handle2PoolId(vbBlk);
    stVideoFrame.enModId = HI_ID_USER;
    stVideoFrame.stVFrame.u32Width = frame->width;
    stVideoFrame.stVFrame.u32Height = frame->height;
    stVideoFrame.stVFrame.enField = VIDEO_FIELD_FRAME;
    stVideoFrame.stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_422;
    stVideoFrame.stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR;
    stVideoFrame.stVFrame.enCompressMode = COMPRESS_MODE_NONE;
    stVideoFrame.stVFrame.enDynamicRange = DYNAMIC_RANGE_SDR8;
    stVideoFrame.stVFrame.enColorGamut = COLOR_GAMUT_BT709;
    stVideoFrame.stVFrame.u32Stride[0] = frame->yuv.stride[0];
    stVideoFrame.stVFrame.u32Stride[1] = frame->yuv.stride[1];
    stVideoFrame.stVFrame.u32Stride[2] = frame->yuv.stride[2];
    stVideoFrame.stVFrame.u64PhyAddr[0] = frame->yuv.phyAddr[0];
    stVideoFrame.stVFrame.u64PhyAddr[1] = frame->yuv.phyAddr[1];
    stVideoFrame.stVFrame.u64PhyAddr[2] = frame->yuv.phyAddr[2];
    stVideoFrame.stVFrame.u64VirAddr[0] = frame->yuv.virAddr[0];
    stVideoFrame.stVFrame.u64VirAddr[1] = frame->yuv.virAddr[1];
    stVideoFrame.stVFrame.u64VirAddr[2] = frame->yuv.virAddr[2];
    stVideoFrame.stVFrame.u32MaxLuminance = 1000U;
    stVideoFrame.stVFrame.u32MinLuminance = 200U;
    stVideoFrame.stVFrame.u32TimeRef = frame->seq * 2U;
    stVideoFrame.stVFrame.u64PTS = frame->pts;

    static JPEG_DCF_S jpegDcf;
    memset(&jpegDcf, 0, sizeof(JPEG_DCF_S));
    stVideoFrame.stVFrame.stSupplement.u64JpegDCFPhyAddr = (HI_U64)(HI_UL)&jpegDcf;
    stVideoFrame.stVFrame.stSupplement.pJpegDCFVirAddr = &jpegDcf;
    PDT_STATEMNG_SendHostUvcFrameToVenc(&stVideoFrame);
    PDT_STATEMNG_SendHostUvcFrameToVo(&stVideoFrame);
    return;
}

HI_VOID PDT_STATEMNG_ResetHostUvcMediaCfg(HI_PDT_MEDIA_CFG_S *mediaCfg)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    HI_U32 fps = 0;
    HI_USB_HostUvcCapability capability;
    HI_USB_HostUvcGetCapability(&capability);
    for (HI_U32 i = 0; i < MIN(capability.capCnt, HI_USB_HOSTUVC_CAP_MAXCNT); i++) {
        if (capability.cap[i].pixelFormat == HI_UVC_STREAM_FORMAT_YUV420 &&
            capability.cap[i].width == stateMngCtx->hostUvc.width &&
            capability.cap[i].height == stateMngCtx->hostUvc.height) {
            fps = (HI_U32)capability.cap[i].fps;
            break;
        }
    }

    HI_PDT_PARAM_HostUvcCfg cfg;
    (HI_VOID)HI_PDT_PARAM_GetHostUvcCfg(&cfg);
    if (cfg.vpss > 0 && cfg.vpss < HI_PDT_MEDIA_VPSS_MAX_CNT) {
        HI_PDT_MEDIA_VPSS_ATTR_S *vpss = &mediaCfg->stVideoCfg.stVprocCfg.astVpssAttr[cfg.vpss];
        vpss->stVpssAttr.u32MaxW = stateMngCtx->hostUvc.width;
        vpss->stVpssAttr.u32MaxH = stateMngCtx->hostUvc.height;
        vpss->astVportAttr[0].stResolution.u32Width = stateMngCtx->hostUvc.width;
        vpss->astVportAttr[0].stResolution.u32Height = stateMngCtx->hostUvc.height;
    }
    for (HI_U32 i = 0; i < HI_PDT_MEDIA_VENC_MAX_CNT; i++) {
        HI_PDT_MEDIA_VENC_CFG_S *venc = &mediaCfg->stVideoCfg.astVencCfg[i];
        if (venc->bEnable != HI_TRUE) {
            continue;
        }
        if (venc->VencHdl == cfg.venc_rec && venc->enVencType == HI_PDT_MEDIA_VENC_TYPE_REC) {
            venc->stVencAttr.stTypeAttr.u32Width = stateMngCtx->hostUvc.width;
            venc->stVencAttr.stTypeAttr.u32Height = stateMngCtx->hostUvc.height;
            if (venc->stVencAttr.stRcAttr.enRcMode == HI_MAPI_VENC_RC_MODE_QVBR) {
                venc->stVencAttr.stRcAttr.unAttr.stH264QVbr.stAttr.u32Gop = fps;
                venc->stVencAttr.stRcAttr.unAttr.stH264QVbr.stAttr.u32SrcFrameRate = fps;
                HI_RECMNG_ATTR_S *recMngAttr =
                    &stateMngCtx->stRecCtx.astRecTaskCtx[PDT_STATEMNG_BACK_CAMID].stRecMngAttr;
                if (recMngAttr->enRecType != HI_REC_TYPE_LAPSE) {
                    venc->stVencAttr.stRcAttr.unAttr.stH264QVbr.stAttr.fr32DstFrameRate = fps;
                }
            } else {
                MLOGW("RC mode is not QVBR.\n");
            }
        }
        if (venc->VencHdl == cfg.venc_sanp && venc->enVencType == HI_PDT_MEDIA_VENC_TYPE_SNAP) {
            venc->stVencAttr.stTypeAttr.u32Width = stateMngCtx->hostUvc.width;
            venc->stVencAttr.stTypeAttr.u32Height = stateMngCtx->hostUvc.height;
        }
    }
    return;
}

HI_S32 PDT_STATEMNG_StartHostUvc(HI_U32 width, HI_U32 height)
{
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    if (stateMngCtx->hostUvc.width == width && stateMngCtx->hostUvc.height == height) {
        MLOGW("width and height not change.\n");
        return HI_SUCCESS;
    }

    MLOGI("Host UVC Connected\n");
    HI_BOOL hostUvcConnected = HI_TRUE;
    HI_BOOL cameraEnable = HI_FALSE;
    HI_S32 ret = HI_PDT_PARAM_GetCamParam(stateMngCtx->enCurrentWorkMode, PDT_STATEMNG_BACK_CAMID,
                                          HI_PDT_PARAM_TYPE_CAM_STATUS, &cameraEnable);
    HI_APPCOMM_CHECK_EXPR_WITHOUT_RETURN(ret == HI_SUCCESS, "get Host UVC cameraEnable");
    if (cameraEnable != hostUvcConnected) {
        MLOGD("hostUvcConnected[%d],cameraEnable[%d],state change\n", hostUvcConnected, cameraEnable);
        /** update cam enable flag */
        ret = HI_PDT_PARAM_SetCamParam(stateMngCtx->enCurrentWorkMode, PDT_STATEMNG_BACK_CAMID,
                                       HI_PDT_PARAM_TYPE_CAM_STATUS, &hostUvcConnected);
        HI_APPCOMM_CHECK_EXPR_WITHOUT_RETURN(ret == HI_SUCCESS, "set Host UVC cameraEnable");
    }
    stateMngCtx->hostUvc.width = width;
    stateMngCtx->hostUvc.height = height;

    if (stateMngCtx->enCurrentWorkMode != HI_PDT_WORKMODE_NORM_REC &&
        stateMngCtx->enCurrentWorkMode != HI_PDT_WORKMODE_PHOTO) {
        stateMngCtx->hostUvc.enable = HI_FALSE;
        return HI_SUCCESS;
    } else {
        stateMngCtx->hostUvc.enable = HI_TRUE;
    }

    ret = PDT_STATEMNG_GetMediaModeCfg(stateMngCtx->enCurrentWorkMode, stateMngCtx->astCamCtx);
    PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "get media mode config");

    /* get media config */
    HI_PDT_MEDIA_CFG_S stMediaCfg;
    ret = HI_PDT_PARAM_GetMediaCfg(stateMngCtx->enCurrentWorkMode, stateMngCtx->astCamCtx, &stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, ret, "get media config");

    /* update disp configure */
    ret = PDT_STATEMNG_UpdateDispCfg(&stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "update video out configure");

    if (stateMngCtx->enCurrentWorkMode == HI_PDT_WORKMODE_NORM_REC) {
        /* get workmode config from Param module */
        HI_PDT_WORKMODE_CFG_S workModeCfg;
        memset(&workModeCfg, 0, sizeof(HI_PDT_WORKMODE_CFG_S));
        ret = HI_PDT_PARAM_GetWorkModeCfg(stateMngCtx->enCurrentWorkMode, &workModeCfg);
        PDT_STATEMNG_CHECK_RET(ret, ret, "get workModeCfg parameter");

        /* generate Rec Context */
        ret = PDT_STATEMNG_GenerateRecCtx(stateMngCtx->enCurrentWorkMode, &workModeCfg,
                                          &stateMngCtx->stRecCtx, &stMediaCfg);
        PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "generate record context");
    }

    /* Reset Media for setting parameter */
    ret = PDT_STATEMNG_ResetMedia(&stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, ret, "reset media");

    /* get OSD param */
    HI_BOOL osd = HI_FALSE;
    ret = HI_PDT_PARAM_GetCamParam(stateMngCtx->enCurrentWorkMode, PDT_STATEMNG_BACK_CAMID, HI_PDT_PARAM_TYPE_OSD,
                                   (HI_VOID *)&osd);
    PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "get osd");
    if (osd == HI_TRUE) {
        /** set the OSD to take effect */
        ret = HI_PDT_MEDIA_SetTimeOSD(PDT_STATEMNG_BACK_CAMID, osd);
        PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "set media TimeOSD");
        ret = HI_PDT_MEDIA_SetLogoOSD(PDT_STATEMNG_BACK_CAMID, osd);
        PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "set media LogoOSD");
    }
    return HI_SUCCESS;
}

HI_S32 PDT_STATEMNG_StopHostUvc(HI_VOID)
{
    MLOGI("Host UVC DisConnected\n");

    HI_BOOL hostUvcConnected = HI_FALSE;
    HI_BOOL cameraEnable = HI_TRUE;
    PDT_STATEMNG_CONTEXT *stateMngCtx = PDT_STATEMNG_GetCtx();
    HI_S32 ret = HI_PDT_PARAM_GetCamParam(stateMngCtx->enCurrentWorkMode, PDT_STATEMNG_BACK_CAMID,
                                          HI_PDT_PARAM_TYPE_CAM_STATUS, &cameraEnable);
    HI_APPCOMM_CHECK_EXPR_WITHOUT_RETURN(ret == HI_SUCCESS, "get Host UVC cameraEnable");
    if (cameraEnable != hostUvcConnected) {
        MLOGD("hostUvcConnected[%d],cameraEnable[%d],state change\n", hostUvcConnected, cameraEnable);
        /** update cam enable flag */
        ret = HI_PDT_PARAM_SetCamParam(stateMngCtx->enCurrentWorkMode, PDT_STATEMNG_BACK_CAMID,
                                       HI_PDT_PARAM_TYPE_CAM_STATUS, &hostUvcConnected);
        HI_APPCOMM_CHECK_EXPR_WITHOUT_RETURN(ret == HI_SUCCESS, "set Host UVC cameraEnable");
    }

    stateMngCtx->hostUvc.width = 0;
    stateMngCtx->hostUvc.height = 0;
    stateMngCtx->s32PreviewCamID = PDT_STATEMNG_FRONT_CAMID;
    if (stateMngCtx->enCurrentWorkMode != HI_PDT_WORKMODE_NORM_REC &&
        stateMngCtx->enCurrentWorkMode != HI_PDT_WORKMODE_PHOTO) {
        stateMngCtx->hostUvc.enable = HI_FALSE;
        return HI_SUCCESS;
    }

    ret = PDT_STATEMNG_GetMediaModeCfg(stateMngCtx->enCurrentWorkMode, stateMngCtx->astCamCtx);
    PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "get media mode config");

    /* get media config */
    HI_PDT_MEDIA_CFG_S stMediaCfg;
    ret = HI_PDT_PARAM_GetMediaCfg(stateMngCtx->enCurrentWorkMode, stateMngCtx->astCamCtx, &stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, ret, "get media config");

    /* update disp configure */
    ret = PDT_STATEMNG_UpdateDispCfg(&stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "update video out configure");

    stateMngCtx->hostUvc.enable = HI_FALSE;

    if (stateMngCtx->enCurrentWorkMode == HI_PDT_WORKMODE_NORM_REC) {
        /* get workmode config from Param module */
        HI_PDT_WORKMODE_CFG_S workModeCfg;
        memset(&workModeCfg, 0, sizeof(HI_PDT_WORKMODE_CFG_S));
        ret = HI_PDT_PARAM_GetWorkModeCfg(stateMngCtx->enCurrentWorkMode, &workModeCfg);
        PDT_STATEMNG_CHECK_RET(ret, ret, "get workModeCfg parameter");

        /* generate Rec Context */
        ret = PDT_STATEMNG_GenerateRecCtx(stateMngCtx->enCurrentWorkMode, &workModeCfg,
                                          &stateMngCtx->stRecCtx, &stMediaCfg);
        PDT_STATEMNG_CHECK_RET(ret, HI_PDT_STATEMNG_EINTER, "generate record context");
    }

    /* Reset Media for setting parameter */
    ret = PDT_STATEMNG_ResetMedia(&stMediaCfg);
    PDT_STATEMNG_CHECK_RET(ret, ret, "reset media");
    return HI_SUCCESS;
}
#endif

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */



